package org.monkey.socket.plugin.provider;

import cn.hutool.json.JSONUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import java.util.ArrayList;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.monkey.common.constant.util.ProtostuffUtil;
import org.monkey.socket.plugin.entity.SocketMsg;
import org.monkey.socket.plugin.service.IMsgDealAction;
import org.monkey.socket.plugin.service.IMsgProducer;
import org.monkey.socket.plugin.service.IMsgSendFailedHandler;
import org.monkey.socket.plugin.service.IMsgSendHandler;

@Slf4j
public class DefaultMsgDealAction implements IMsgDealAction {
  private List<IMsgSendHandler> msgSendHandlers;
  private IMsgProducer msgProducer;
  private IMsgSendFailedHandler msgSendFailedHandler;

  public DefaultMsgDealAction(IMsgProducer msgProducer,
      IMsgSendFailedHandler msgSendFailedHandler) {
    this.msgProducer = msgProducer;
    this.msgSendFailedHandler = msgSendFailedHandler;
  }

  @Override
  public boolean dealMsg(ChannelHandlerContext ctx, String text) {
    log.info("accept msg：{}", text);
    if (JSONUtil.isTypeJSON(text)) {
      SocketMsg socketMsg;
      try {
        socketMsg = JSONUtil.toBean(text, SocketMsg.class);
      } catch (Exception e) {
        log.error("msg deserialize failed:{}", text);
        log.error("exception msg:", e);
        if(ctx!=null) {
          ctx.writeAndFlush(new TextWebSocketFrame(text));
          return true;
        }else{
          return false;
        }
      }
      try {
        boolean publish = true;
        if (msgSendHandlers != null) {
          for (IMsgSendHandler iMsgSendHandler : msgSendHandlers) {
            if (socketMsg != null) {
              publish = iMsgSendHandler.handlerMsg(ctx, socketMsg);
            }
          }
        }
        if (publish) {
          msgProducer.producer(ProtostuffUtil.serialize(socketMsg));
        }
        return true;
      } catch (Exception e) {
        log.error("msg send failed:{},", socketMsg, e);
        msgSendFailedHandler.handlerFail(ctx, socketMsg, e);
        return false;
      }
    } else {
      if(ctx!=null) {
        ctx.writeAndFlush(new TextWebSocketFrame(text));
        return true;
      }else{
        return false;
      }
    }
  }
  public DefaultMsgDealAction addSendHandler(IMsgSendHandler iMsgSendHandler) {
    if (msgSendHandlers == null) {
      msgSendHandlers = new ArrayList<>();
    }
    msgSendHandlers.add(iMsgSendHandler);
    return this;
  }
}
